package org.rsbot.event;

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import org.rsbot.event.events.RSEvent;
import org.rsbot.event.listeners.CharacterMovedListener;
import org.rsbot.event.listeners.MessageListener;
import org.rsbot.event.listeners.PaintListener;
import org.rsbot.event.listeners.ServerMessageListener;
import org.rsbot.event.listeners.TextPaintListener;

public class EventMulticaster
  implements EventListener
{
  public static final long FOCUS_EVENT = 16L;
  public static final long KEY_EVENT = 8L;
  public static final long MOUSE_EVENT = 1L;
  public static final long MOUSE_MOTION_EVENT = 2L;
  public static final long MOUSE_WHEEL_EVENT = 4L;
  public static final long CHARACTER_MOVED_EVENT = 1024L;
  public static final long SERVER_MESSAGE_EVENT = 1536L;
  public static final long MESSAGE_EVENT = 2048L;
  public static final long PAINT_EVENT = 4096L;
  public static final long TEXT_PAINT_EVENT = 8192L;
  private static final Object treeLock = new Object();
  private long enabledMask;
  private final List<Long> listenerMasks = new ArrayList();

  private final List<EventListener> listeners = new ArrayList(5);
  private EventMulticaster parent;

  public static long getDefaultMask(EventListener paramEventListener)
  {
    if ((paramEventListener instanceof EventMulticaster)) {
      EventMulticaster localEventMulticaster = (EventMulticaster)paramEventListener;
      return localEventMulticaster.enabledMask;
    }
    int i = 0;
    if ((paramEventListener instanceof MouseListener)) {
      i = (int)(i | 1L);
    }
    if ((paramEventListener instanceof MouseMotionListener)) {
      i = (int)(i | 0x2);
    }
    if ((paramEventListener instanceof MouseWheelListener)) {
      i = (int)(i | 0x4);
    }
    if ((paramEventListener instanceof KeyListener)) {
      i = (int)(i | 0x8);
    }
    if ((paramEventListener instanceof FocusListener)) {
      i = (int)(i | 0x10);
    }

    if ((paramEventListener instanceof CharacterMovedListener)) {
      i = (int)(i | 0x400);
    }

    if ((paramEventListener instanceof ServerMessageListener)) {
      i = (int)(i | 0x600);
    }
    if ((paramEventListener instanceof MessageListener)) {
      i = (int)(i | 0x800);
    }
    if ((paramEventListener instanceof PaintListener)) {
      i = (int)(i | 0x1000);
    }
    if ((paramEventListener instanceof TextPaintListener)) {
      i = (int)(i | 0x2000);
    }

    return i;
  }

  public static long getDefaultMask(EventObject paramEventObject)
  {
    long l = 0L;
    Object localObject;
    if ((paramEventObject instanceof MouseEvent)) {
      localObject = (MouseEvent)paramEventObject;
      switch (((MouseEvent)localObject).getID()) {
      case 500:
      case 501:
      case 502:
      case 504:
      case 505:
        l |= 1L;
        break;
      case 503:
      case 506:
        l |= 2L;
        break;
      case 507:
        l |= 4L;
      }
    }
    else if ((paramEventObject instanceof FocusEvent)) {
      localObject = (FocusEvent)paramEventObject;
      switch (((FocusEvent)localObject).getID()) {
      case 1004:
      case 1005:
        l |= 16L;
      }
    }
    else if ((paramEventObject instanceof KeyEvent)) {
      localObject = (KeyEvent)paramEventObject;
      switch (((KeyEvent)localObject).getID()) {
      case 400:
      case 401:
      case 402:
        l |= 8L;
      }
    }
    else if ((paramEventObject instanceof RSEvent)) {
      localObject = (RSEvent)paramEventObject;
      l |= ((RSEvent)localObject).getMask();
    }
    return l;
  }

  public void addListener(EventListener paramEventListener)
  {
    long l = 0L;
    if ((paramEventListener instanceof EventMulticaster)) {
      EventMulticaster localEventMulticaster = (EventMulticaster)paramEventListener;
      l = localEventMulticaster.enabledMask;
    } else {
      l = getDefaultMask(paramEventListener);
    }
    addListener(paramEventListener, l);
  }

  public void addListener(EventListener paramEventListener, long paramLong)
  {
    synchronized (treeLock) {
      if (this.listeners.contains(paramEventListener)) {
        return;
      }
      if ((paramEventListener instanceof EventMulticaster)) {
        EventMulticaster localEventMulticaster = (EventMulticaster)paramEventListener;
        addMulticaster(localEventMulticaster);
        paramLong = localEventMulticaster.enabledMask;
      } else {
        this.listeners.add(paramEventListener);
      }
      this.listenerMasks.add(Long.valueOf(paramLong));

      cleanMasks();
    }
  }

  private void addMulticaster(EventMulticaster paramEventMulticaster)
  {
    if (paramEventMulticaster.parent != null)
      throw new IllegalArgumentException("adding multicaster to multiple multicasters");
    for (EventMulticaster localEventMulticaster = this; localEventMulticaster != null; localEventMulticaster = localEventMulticaster.parent) {
      if (localEventMulticaster == paramEventMulticaster)
        throw new IllegalArgumentException("adding multicaster's parent to itself");
    }
    this.listeners.add(paramEventMulticaster);
    paramEventMulticaster.parent = this;
  }

  private void cleanMasks()
  {
    for (EventMulticaster localEventMulticaster1 = this; localEventMulticaster1 != null; localEventMulticaster1 = localEventMulticaster1.parent) {
      int i = 0;
      int j = localEventMulticaster1.listeners.size();
      for (int k = 0; k < j; k++) {
        EventListener localEventListener = (EventListener)localEventMulticaster1.listeners.get(k);
        long l = ((Long)localEventMulticaster1.listenerMasks.get(k)).longValue();
        if ((localEventListener instanceof EventMulticaster)) {
          EventMulticaster localEventMulticaster2 = (EventMulticaster)localEventListener;
          if (localEventMulticaster2.enabledMask != l) {
            l = localEventMulticaster2.enabledMask;
            localEventMulticaster1.listenerMasks.set(k, Long.valueOf(l));
          }
        }
        i = (int)(i | l);
      }
      if (i == localEventMulticaster1.enabledMask) {
        break;
      }
      localEventMulticaster1.enabledMask = i;
    }
  }

  public void fireEvent(EventObject paramEventObject)
  {
    fireEvent(paramEventObject, getDefaultMask(paramEventObject));
  }

  public void fireEvent(EventObject paramEventObject, long paramLong)
  {
    synchronized (treeLock) {
      int i = this.listeners.size();
      for (int j = 0; j < i; j++) {
        long l = ((Long)this.listenerMasks.get(j)).longValue();
        if ((l != 12288L) && ((l & paramLong) == 0L)) {
          continue;
        }
        EventListener localEventListener = (EventListener)this.listeners.get(j);
        Object localObject1;
        if ((paramEventObject instanceof MouseEvent)) {
          localObject1 = (MouseEvent)paramEventObject;
          switch (((MouseEvent)localObject1).getID()) {
          case 501:
            ((MouseListener)localEventListener).mousePressed((MouseEvent)localObject1);
            break;
          case 502:
            ((MouseListener)localEventListener).mouseReleased((MouseEvent)localObject1);
            break;
          case 500:
            ((MouseListener)localEventListener).mouseClicked((MouseEvent)localObject1);
            break;
          case 504:
            ((MouseListener)localEventListener).mouseEntered((MouseEvent)localObject1);
            break;
          case 505:
            ((MouseListener)localEventListener).mouseExited((MouseEvent)localObject1);
            break;
          case 503:
            ((MouseMotionListener)localEventListener).mouseMoved((MouseEvent)localObject1);
            break;
          case 506:
            ((MouseMotionListener)localEventListener).mouseDragged((MouseEvent)localObject1);
            break;
          case 507:
            ((MouseWheelListener)localEventListener).mouseWheelMoved((MouseWheelEvent)localObject1);
          }
        }
        else if ((paramEventObject instanceof FocusEvent)) {
          localObject1 = (FocusEvent)paramEventObject;
          switch (((FocusEvent)localObject1).getID()) {
          case 1004:
            ((FocusListener)localEventListener).focusGained((FocusEvent)localObject1);
            break;
          case 1005:
            ((FocusListener)localEventListener).focusLost((FocusEvent)localObject1);
          }
        }
        else if ((paramEventObject instanceof KeyEvent)) {
          localObject1 = (KeyEvent)paramEventObject;
          switch (((KeyEvent)localObject1).getID()) {
          case 400:
            ((KeyListener)localEventListener).keyTyped((KeyEvent)localObject1);
            break;
          case 401:
            ((KeyListener)localEventListener).keyPressed((KeyEvent)localObject1);
            break;
          case 402:
            ((KeyListener)localEventListener).keyReleased((KeyEvent)localObject1);
          }
        }
        else if ((paramEventObject instanceof RSEvent)) {
          localObject1 = (RSEvent)paramEventObject;
          ((RSEvent)localObject1).dispatch(localEventListener);
        }
      }
    }
  }

  public long getEnabledMask()
  {
    return this.enabledMask;
  }

  public List<EventListener> getListeners()
  {
    return Collections.unmodifiableList(this.listeners);
  }

  public final boolean isEnabled(long paramLong)
  {
    return (this.enabledMask & paramLong) != 0L;
  }

  public void removeListener(EventListener paramEventListener)
  {
    synchronized (treeLock) {
      int i = this.listeners.indexOf(paramEventListener);
      if (i == -1)
        return;
      paramEventListener = (EventListener)this.listeners.remove(i);
      if ((paramEventListener instanceof EventMulticaster)) {
        EventMulticaster localEventMulticaster = (EventMulticaster)paramEventListener;
        localEventMulticaster.parent = null;
      }
      this.listenerMasks.remove(i);
      cleanMasks();
    }
  }
}